package com.ys.util;

import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsGridCol;
import com.ys.mapper.business.DiySqlMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 参数验证工具类
 */
@Component
public class CheckUtil {

    @Autowired
    private DiySqlMapper diySqlMapper;


    /**
     * 验证需要必填字段的非空；所有字段长度、类型（主要验证数字类型）
     * @param tableName 表名
     * @param listField YsCol表相应设置，即为需要验证的参数
     * @param params 要验证的参数
     * @param notNullCondition 非空判断依据的函数条件（通常是YsCol表中FormEditRequired=1,或者新增必填字段等：ysColItem->ysColItem.getFormEditRequired() == 1 ）
     * @return 错误信息
     */
    public String checkTableColLengthAndDataType(String tableName, List<YsCol> listField, Map<String, Object> params,Predicate<YsCol> notNullCondition) throws Exception {
        String backMsg = "";
        if(params==null){
            return "参数为空！";
        }
        //获取数据库设置的字段长度限制
        List<Map<String, Object>> tableColLengthAndDataType = diySqlMapper.getTableColLengthAndDataType(tableName);
        if(listField!=null && listField.size()>0) {
            for (YsCol ysCol : listField) {
                //编辑必填字段非空验证
                if (isNullByObject(params.get(ysCol.getCode())) && notNullCondition.test(ysCol)) {
                    backMsg = ysCol.getName() + "为空！";
                    continue;
                }
                //字段长度、类型验证
                if(tableColLengthAndDataType!=null && tableColLengthAndDataType.size()>0){
                    for(Map<String, Object> colSetItem:tableColLengthAndDataType){
                        //获取到对应的字段名称
                        if(colSetItem.get("colName").toString().toLowerCase().equals(ysCol.getCode().toLowerCase()) && isNotNullByObject(params.get(ysCol.getCode()))){
                            //字段长度验证
                            if(colSetItem.get("maxLength")!=null){
                                if(params.get(ysCol.getCode()).toString().length()>Integer.parseInt(colSetItem.get("maxLength").toString())){
                                    backMsg = ysCol.getName()+"输入的长度超出限制，不能大于"+colSetItem.get("maxLength")+"！";
                                }
                            }
                            //数字验证
                            if(colSetItem.get("dataType").toString().equals("decimal") && !checkNumber(params.get(ysCol.getCode()).toString())){
                                backMsg = ysCol.getName()+"应为数字！";
                                continue;
                            }
                            //整数验证
                            if(colSetItem.get("dataType").toString().equals("int") && !isInt(params.get(ysCol.getCode()).toString())){
                                backMsg = ysCol.getName()+"应为整数数字！";
                                continue;
                            }
                            //小数验证
                            if(colSetItem.get("dataType").toString().equals("decimal") && !isDecimal(params.get(ysCol.getCode()).toString(),colSetItem.get("numericScale").toString())){
                                backMsg = ysCol.getName()+"应为"+colSetItem.get("numericScale")+"位小数数字！";
                                continue;
                            }
                        }
                    }
                }
            }
        }
        return backMsg;
    }




    /**
     * 子表字段 ** 验证需要必填字段的非空；所有字段长度、类型（主要验证数字类型）
     * @param tableName 表名
     * @param listField YsGridCol表相应设置，即为需要验证的参数
     * @param params 要验证的参数
     * @param notNullCondition 非空判断依据的函数条件
     * @return 错误信息
     */
    public String checkTableColLengthAndDataTypeByGrid(String tableName, List<YsGridCol> listField, Map<String, Object> params, Predicate<YsGridCol> notNullCondition) throws Exception {
        String backMsg = "";
        if(params==null){
            return "参数为空！";
        }
        //获取数据库设置的字段长度限制
        List<Map<String, Object>> tableColLengthAndDataType = diySqlMapper.getTableColLengthAndDataType(tableName);
        if(listField!=null && listField.size()>0) {
            for (YsGridCol ysGridCol : listField) {
                //编辑必填字段非空验证
                if (isNullByObject(params.get(ysGridCol.getCode())) && notNullCondition.test(ysGridCol)) {
                    backMsg = ysGridCol.getName() + "为空！";
                    continue;
                }
                //字段长度、类型验证
                if(tableColLengthAndDataType!=null && tableColLengthAndDataType.size()>0){
                    for(Map<String, Object> colSetItem:tableColLengthAndDataType){
                        //获取到对应的字段名称
                        if(colSetItem.get("colName").toString().toLowerCase().equals(ysGridCol.getCode().toLowerCase()) && isNotNullByObject(params.get(ysGridCol.getCode()))){
                            //字段长度验证
                            if(colSetItem.get("maxLength")!=null){
                                if(params.get(ysGridCol.getCode()).toString().length()>Integer.parseInt(colSetItem.get("maxLength").toString())){
                                    backMsg = ysGridCol.getName()+"输入的长度超出限制，不能大于"+colSetItem.get("maxLength")+"！";
                                }
                            }
                            //数字验证
                            if(colSetItem.get("dataType").toString().equals("decimal") && !checkNumber(params.get(ysGridCol.getCode()).toString())){
                                backMsg = ysGridCol.getName()+"应为数字！";
                                continue;
                            }
                            //整数验证
                            if(colSetItem.get("dataType").toString().equals("int") && !isInt(params.get(ysGridCol.getCode()).toString())){
                                backMsg = ysGridCol.getName()+"应为整数数字！";
                                continue;
                            }
                            //小数验证
                            if(colSetItem.get("dataType").toString().equals("decimal") && !isDecimal(params.get(ysGridCol.getCode()).toString(),colSetItem.get("numericScale").toString())){
                                backMsg = ysGridCol.getName()+"应为"+colSetItem.get("numericScale")+"位小数数字！";
                                continue;
                            }
                        }
                    }
                }
            }
        }
        return backMsg;
    }

    /**
     * 是否是数字
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean isNumber(String input){
        return input.matches("-?\\d+(\\.\\d+)?");
    }



    /**
     * 是否是小数
     * @param input 参数，decimalCount小数位数
     * @return 返回：是ture；否false
     */
    public boolean isDecimal(String input,String decimalCount){
        String  regular = "^(\\-+)?\\d+(\\.\\d{0,"+decimalCount+"})?$";
        return  input.matches(regular);
    }

    /**
     * 是否是整数
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean isInt(String input){
        if (!isNumber(input)) {//是否是数字
            return false;
        }
        BigDecimal num = new BigDecimal(input);
        BigDecimal numByDown = num.setScale(0, BigDecimal.ROUND_DOWN);
        if (numByDown.compareTo(num)==0) {
            return true;
        }else {
            return false;
        }
    }


    /**
     * 是否是正整数
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean isPositiveInteger(String input){
        if (!isNumber(input)) {//是否是数字
            return false;
        }
        if (isInt(input)) {
            if(new BigDecimal(input).compareTo(BigDecimal.ZERO)>0){
                return true;
            }else {
                return false;
            }
        }else {
            return false;
        }
    }


    /**
     * 是否是0或正整数
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean isZeroOrPositiveInt(String input){
        if (!isNumber(input)) {//是否是数字
            return false;
        }
        if (isInt(input)) {
            if(new BigDecimal(input).compareTo(BigDecimal.ZERO)>=0){
                return true;
            }else {
                return false;
            }
        }else {
            return false;
        }
    }

    /**
     * 是否正数、负数、小数
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean checkNumber(String input){
        Pattern pattern = Pattern.compile("^(\\-+)?\\d+(\\.\\d+)?$");
        Matcher matcher = pattern.matcher(input);
        return matcher.matches();
    }

    /**
     * 是否为0
     * @param input 参数
     * @return 返回：是ture；否false
     */
    public boolean isZero(String input){
        if (!input.matches("\\d+")) {//是否是数字
            return false;
        }
        if(new BigDecimal(input).compareTo(BigDecimal.ZERO)!=0){
            return false;
        }else {
            return true;
        }


    }



    /**
     * 是否不为空
     * @param input 参数
     * @return 返回：非空true，空false
     */
    public boolean isNotNullByObject(Object input){
        return input!=null && !"".equals(input.toString().trim());
    }

    /**
     * 是否为空
     * @param input 参数
     * @return 返回：空true，非空false
     */
    public boolean isNullByObject(Object input){
        return !isNotNullByObject(input);
    }

    /**
     * 是否为手机号
     * @param phone 参数
     * @return 返回：是true，否false
     */
    public boolean isPhone(String phone){
        /*电话号码验证
        Pattern p1 = null, p2 = null;
        Matcher m = null;
        boolean b = false;
        p1 = Pattern.compile("^[0][1-9]{2,3}-[0-9]{5,10}$");  // 验证带区号的
        p2 = Pattern.compile("^[1-9]{1}[0-9]{5,8}$");         // 验证没有区号的
        if (phone.length() > 9) {
            m = p1.matcher(phone);
            b = m.matches();
        } else {
            m = p2.matcher(phone);
            b = m.matches();
        }
        return b;
        */
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); // 验证手机号
        m = p.matcher(phone);
        b = m.matches();
        return b;
    }

    /**
     * 是否为身份证号码
     * @param idNumber 参数
     * @return 返回：是true，否false
     */
    public boolean isIDNumberValid(String idNumber) {
        // 验证身份证号码的长度
        if (idNumber.length() != 18) {
            return false;
        }

        // 验证身份证号码的前17位是否全为数字
        String numberPart = idNumber.substring(0, 17);
        if (!numberPart.matches("\\d+")) {
            return false;
        }

        // 验证身份证号码的最后一位校验码
        char checkDigit = idNumber.charAt(17);
        char calculatedCheckDigit = calculateCheckDigit(idNumber.substring(0, 17));
        if (checkDigit != calculatedCheckDigit) {
            return false;
        }

        return true;
    }

    // 验证身份证号码的最后一位校验码
    public char calculateCheckDigit(String idNumberWithoutCheckDigit) {
        int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char[] checkDigits = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

        int sum = 0;
        for (int i = 0; i < idNumberWithoutCheckDigit.length(); i++) {
            char digit = idNumberWithoutCheckDigit.charAt(i);
            int weight = weights[i];
            sum += (digit - '0') * weight;
        }

        int remainder = sum % 11;
        return checkDigits[remainder];
    }







}
